package io.github.yotta.common.api.model;

import io.github.yotta.common.api.exception.ServiceException;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * @author yotta
 * @date 2022/11/7 17:35
 */
@EqualsAndHashCode
@ToString
@Data
@NoArgsConstructor
public class Response<T> implements Serializable {

    private final static Integer SERVER_ERROR_CODE = 500;

    private final static Integer SUCCESS_CODE = 200;

    private  T data;

    private  String error;

    private  boolean success;

    public  Integer code;

    public Response(T data, String error, boolean success, Integer code) {
        this.data = data;
        this.error = error;
        this.success = success;
        this.code = code;
    }

    public static <T> Response<T> ok(T data) {
        return new Response<T>(data, null, true, SUCCESS_CODE);
    }

    public static <T> Response<T> fail(String error) {
        return Response.fail(error, SERVER_ERROR_CODE);
    }

    public static <T> Response<T> fail(String error, Integer code) {

        return new Response<T>(null, error, false, code);
    }
    public T orElse(T otherData) {
        return this.success ? data : otherData;
    }

    public T orElseGet(Supplier<? extends T> supplier) {
        return this.success ? data : supplier.get();
    }


    public void ifSuccess(Consumer<? super T> action) {
        if (this.success) {
            action.accept(data);
        }
    }

    public T orElseThrow() throws Throwable {
        if (this.success) {
            return this.data;
        } else {
            throw new ServiceException(this.error);
        }
    }


    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (this.success) {
            return this.data;
        } else {
            throw exceptionSupplier.get();
        }
    }


}
